//
//  API_AsyncSequence_NetworkVC.swift
//  APSwift
//
//  Created by jianbo.pei on 2024/8/16.
//

import UIKit
import Network

class API_AsyncSequence_NetworkVC: UIViewController {
    
    // UI 组件
    private lazy var startButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("开始监控", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
        button.backgroundColor = UIColor.systemBlue
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    private lazy var stopButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("停止监控", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        button.backgroundColor = UIColor.systemRed
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    private lazy var statusLabel: UILabel = {
        let label = UILabel()
        label.text = "网络监控未启动"
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 16)
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    private lazy var networkInfoLabel: UILabel = {
        let label = UILabel()
        label.text = "网络信息将在这里显示"
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 14)
        label.numberOfLines = 0
        label.backgroundColor = UIColor.systemGray6
        label.layer.cornerRadius = 8
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    private lazy var logTextView: UITextView = {
        let textView = UITextView()
        textView.isEditable = false
        textView.font = UIFont.monospacedSystemFont(ofSize: 14, weight: .regular)
        textView.backgroundColor = UIColor.systemGray6
        textView.layer.cornerRadius = 8
        textView.translatesAutoresizingMaskIntoConstraints = false
        return textView
    }()
    
    // 网络监控器和任务
    private var networkMonitor: NetworkAsyncMonitor?
    private var monitorTask: Task<Void, Never>?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupNetworkMonitor()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 取消监控任务
        monitorTask?.cancel()
        networkMonitor?.stopMonitoring()
    }
    
    private func setupUI() {
        view.backgroundColor = .white
        title = "网络监控 AsyncSequence 示例"
        
        view.addSubview(startButton)
        view.addSubview(stopButton)
        view.addSubview(statusLabel)
        view.addSubview(networkInfoLabel)
        view.addSubview(logTextView)
        
        NSLayoutConstraint.activate([
            startButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
            startButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
            startButton.widthAnchor.constraint(equalToConstant: 120),
            startButton.heightAnchor.constraint(equalToConstant: 50),
            
            stopButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50),
            stopButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
            stopButton.widthAnchor.constraint(equalToConstant: 120),
            stopButton.heightAnchor.constraint(equalToConstant: 50),
            
            statusLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            statusLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            statusLabel.topAnchor.constraint(equalTo: startButton.bottomAnchor, constant: 30),
            
            networkInfoLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            networkInfoLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            networkInfoLabel.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 20),
            networkInfoLabel.heightAnchor.constraint(equalToConstant: 80),
            
            logTextView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            logTextView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            logTextView.topAnchor.constraint(equalTo: networkInfoLabel.bottomAnchor, constant: 20),
            logTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
        ])
        
        // 添加按钮事件
        startButton.addTarget(self, action: #selector(startMonitoring), for: .touchUpInside)
        stopButton.addTarget(self, action: #selector(stopMonitoring), for: .touchUpInside)
        
        // 初始状态
        stopButton.isEnabled = false
    }
    
    private func setupNetworkMonitor() {
        networkMonitor = NetworkAsyncMonitor()
    }
    
    @objc private func startMonitoring() {
        guard let monitor = networkMonitor else { return }
        
        startButton.isEnabled = false
        stopButton.isEnabled = true
        statusLabel.text = "网络监控已启动"
        
        appendLog("开始网络监控...")
        
        monitorTask = Task { [weak self] in
            guard let self = self else { return }
            
            do {
                for try await status in monitor.networkStatusStream {
                    if Task.isCancelled { break }
                    
                    await MainActor.run {
                        self.handleNetworkStatusChange(status)
                    }
                }
            } catch {
                await MainActor.run {
                    self.appendLog("网络监控错误: \(error)")
                    self.stopMonitoring()
                }
            }
        }
        
        monitor.startMonitoring()
    }
    
    @objc private func stopMonitoring() {
        networkMonitor?.stopMonitoring()
        monitorTask?.cancel()
        monitorTask = nil
        
        startButton.isEnabled = true
        stopButton.isEnabled = false
        statusLabel.text = "网络监控已停止"
        
        appendLog("停止网络监控")
    }
    
    private func handleNetworkStatusChange(_ status: NetworkStatus) {
        let timestamp = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
        
        // 更新状态标签
        statusLabel.text = "网络状态: \(status.isConnected ? "已连接" : "未连接")"
        
        // 更新网络信息
        var infoText = "连接状态: \(status.isConnected ? "✅ 已连接" : "❌ 未连接")\n"
        infoText += "连接类型: \(status.connectionType)\n"
        infoText += "是否昂贵: \(status.isExpensive ? "是" : "否")\n"
        infoText += "是否受限: \(status.isConstrained ? "是" : "否")"
        
        networkInfoLabel.text = infoText
        
        // 添加日志
        let logMessage = "[\(timestamp)] 网络状态变更: \(status.connectionType) (连接: \(status.isConnected))"
        appendLog(logMessage)
    }
    
    private func appendLog(_ message: String) {
        let currentText = logTextView.text ?? ""
        logTextView.text = currentText + message + "\n"
        
        // 滚动到底部
        let bottom = NSMakeRange(logTextView.text.count - 1, 1)
        logTextView.scrollRangeToVisible(bottom)
    }
}

// MARK: - 网络状态数据模型
struct NetworkStatus {
    let isConnected: Bool
    let connectionType: String
    let isExpensive: Bool
    let isConstrained: Bool
    let path: NWPath
    
    init(path: NWPath) {
        self.path = path
        self.isConnected = path.status == .satisfied
        self.isExpensive = path.isExpensive
        self.isConstrained = path.isConstrained
        
        // 确定连接类型
        if path.usesInterfaceType(.wifi) {
            self.connectionType = "WiFi"
        } else if path.usesInterfaceType(.cellular) {
            self.connectionType = "蜂窝网络"
        } else if path.usesInterfaceType(.wiredEthernet) {
            self.connectionType = "以太网"
        } else if path.usesInterfaceType(.loopback) {
            self.connectionType = "本地回环"
        } else {
            self.connectionType = "其他"
        }
    }
}

// MARK: - 网络异步监控器
class NetworkAsyncMonitor {
    private let monitor = NWPathMonitor()
    private let queue = DispatchQueue(label: "NetworkMonitor")
    private var continuation: AsyncStream<NetworkStatus>.Continuation?
    
    // 网络状态流
    lazy var networkStatusStream: AsyncStream<NetworkStatus> = {
        AsyncStream { continuation in
            self.continuation = continuation
            
            continuation.onTermination = { _ in
                self.continuation = nil
            }
        }
    }()
    
    func startMonitoring() {
        monitor.pathUpdateHandler = { [weak self] path in
            let status = NetworkStatus(path: path)
            self?.continuation?.yield(status)
        }
        
        monitor.start(queue: queue)
    }
    
    func stopMonitoring() {
        monitor.cancel()
        continuation?.finish()
    }
}